Array.prototype.pushArray = function () {
	this.push.apply(this, this.concat.apply([], arguments));
};
if (!String.prototype.contains) {
	String.prototype.contains = function (str) {
		return this.indexOf(str) > -1;
	};
}
var __NTUBE_NEXT_NETWORK_SPEED = -1;
const nTubeNext = {};
nTubeNext.apiVersion = "0.1.7-NX";
/* Deprecated? */
nTubeNext.AcceleratedImage = {
	// class: accelerated-image
	// src: default
	// full-src: full image
	init: function () {},
	getAccelerationMethod: function () {
		if ("IntersectionObserver" in window) {
			return "InterObserver";
		} else if (typeof Element.prototype.getBoundingClientRect === "function") {
			return "getBoundRect";
		} else {
			return "UNSUPPORTED";
		}
	},
};
nTubeNext.NetworkThroughput = {
	FALLBACK_SPEED: 253952, // 469 KB
	NEW_TEST_CHUNK_TYPE_NAME: "test-chunk",
	NEW_TEST_NORMAL_CHUNK_SIZES: [4096, 65536, 131072, 262144, 524288],
	NEW_TEST_LARGE_CHUNK_SIZES: [1048576, 2097152, 4194304],
	NEW_TEST_SMALL_RTT_THRESHOLD: 480,
	NEW_TEST_LARGE_RTT_THRESHOLD: 960,
	get: function () {
		if (navigator.connection && navigator.connection.downlink) {
			try {
				const LIMIT = 60 * 81920;
				var chunkSize = navigator.connection.downlink * 81920;
				if (chunkSize > LIMIT) {
					chunkSize = LIMIT;
				}
				const HIGHER_CHUNK_RTT_LIMIT = 850;
				if (navigator.connection.rtt > HIGHER_CHUNK_RTT_LIMIT) {
					chunkSize /= 1.4;
					if (chunkSize % 2 !== 0) {
						while (chunkSize % 2 !== 0) {
							chunkSize -= 1;
						}
					}
				}
				if (navigator.connection.effectiveType === "4g") {
					chunkSize *= 2;
					if (chunkSize % 2 !== 0) {
						while (chunkSize % 2 !== 0) {
							chunkSize += 1;
						}
					}
				}
				return chunkSize;
			} catch (e) {
				console.error(e);
				return this.FALLBACK_SPEED;
			}
		} else {
			if (sessionStorage.getItem("ntube-next-cached-throughput")) {
				return parseInt(sessionStorage.getItem("ntube-next-cached-throughput"));
			} else {
				return nTubeNext.NetworkThroughput.runThroughputTest()
					.then(function (throughput) {
						sessionStorage.setItem("ntube-next-cached-throughput", throughput);
					})
					.catch(function (error) {
						console.error("[NetworkThroughput::get]", error);
					});
			}
		}
	},
	__obj_length: function (obj) {
		if (Object.keys) {
			return Object.keys(obj).length;
		} else {
			var count = 0;

			for (var prop in obj) {
				if (obj.hasOwnProperty(prop)) ++count;
			}

			return count;
		}
	},
	__get_url: function () {
		if (location.protocol === "https:") {
			return "wss://" + location.host + "/api/network/throughput_test_ws";
		} else {
			return "ws://" + location.host + "/api/network/throughput_test_ws";
		}
	},
	runThroughputTest: function () {
		return new Promise(function (resolveFunc, rejectFunc) {
			try {
				const __test_ws = new WebSocket(nTubeNext.NetworkThroughput.__get_url());
				__test_ws.addEventListener("open", function (event) {
					__test_ws.send(JSON.stringify({ type: "ntube-start-throughput-test" }));
				});
				const __test_tbl = {};
				__test_ws.addEventListener("message", function (event) {
					const rcvAt = Date.now();
					if (typeof event.data === "string") {
						const jsonObject = JSON.parse(event.data);
						if (jsonObject["type"] && jsonObject["type"] === nTubeNext.NetworkThroughput.NEW_TEST_CHUNK_TYPE_NAME) {
							__test_tbl[jsonObject["size"]] = {
								sent: jsonObject["timestamp"],
								got: rcvAt,
							};
						} else {
							console.warn("runThroughputTest: Received unknown text packet: ", jsonObject);
						}
					} else if (typeof event.data === "object") {
						/* Ignored. */
					} else {
						throw new Error("Unknown object type: " + typeof event.data);
					}
				});
				__test_ws.addEventListener("error", function (event) {
					rejectFunc(event);
				});
				__test_ws.addEventListener("close", function (event) {
					var highestThroughput = -1;
					if (nTubeNext.NetworkThroughput.__obj_length(__test_tbl) == 0) {
						/* Uhh...*/
						resolveFunc(nTubeNext.NetworkThroughput.FALLBACK_SPEED);
						return;
					}
					for (var x = 0; x < nTubeNext.NetworkThroughput.NEW_TEST_NORMAL_CHUNK_SIZES.length; x++) {
						const inst0 = nTubeNext.NetworkThroughput.NEW_TEST_NORMAL_CHUNK_SIZES[x];
						const rtt0 = __test_tbl[inst0]["got"] - __test_tbl[inst0]["sent"];
						if (rtt0 > nTubeNext.NetworkThroughput.NEW_TEST_SMALL_RTT_THRESHOLD) {
							continue;
						} else if (inst > highestThroughput) {
							highestThroughput = inst0;
						} else {
							/* Do nothing. */
						}
					}
					if (__test_tbl[nTubeNext.NetworkThroughput.NEW_TEST_LARGE_CHUNK_SIZES[0]]) {
						for (var x = 0; x < nTubeNext.NetworkThroughput.NEW_TEST_LARGE_CHUNK_SIZES.length; x++) {
							const inst1 = nTubeNext.NetworkThroughput.NEW_TEST_LARGE_CHUNK_SIZES[x];
							const rtt1 = __test_tbl[inst1]["got"] - __test_tbl[inst1]["sent"];
							if (rtt1 > nTubeNext.NetworkThroughput.NEW_TEST_LARGE_RTT_THRESHOLD) {
								continue;
							} else if (inst > highestThroughput) {
								highestThroughput = inst1;
							} else {
								/* Do nothing. */
							}
						}
					}
					if (highestThroughput == -1) {
						highestThroughput = nTubeNext.NetworkThroughput.FALLBACK_SPEED;
					}
					resolveFunc(highestThroughput);
				});
			} catch (e) {
				rejectFunc(e);
			}
		});
	},
	getXHRObject: function () {
		try {
			return new XMLHttpRequest();
		} catch (e) {}
		try {
			return new ActiveXObject("Msxml3.XMLHTTP");
		} catch (e) {}
		try {
			return new ActiveXObject("Msxml2.XMLHTTP.6.0");
		} catch (e) {}
		try {
			return new ActiveXObject("Msxml2.XMLHTTP.3.0");
		} catch (e) {}
		try {
			return new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {}
		try {
			return new ActiveXObject("Microsoft.XMLHTTP");
		} catch (e) {}
		return null;
	},
};
nTubeNext.VideoAcceleration = {
	isSupported: function () {
		try {
			return "mediaCapabilities" in navigator && "decodingInfo" in navigator.mediaCapabilities;
		} catch (e) {
			console.error(e);
			return false;
		}
	},
	AccelerationResult: {
		FULLY_ACCELERATED: "HARDWARE_ACCELERATED",
		SEMI_ACCELERATED: "SOFTWARE_ACCELERATED",
		UNACCELERATED: "SOFTWARE",
		UNSUPPORTED: "UNDECODABLE",
	},
	randomInt: function (min, max) {
		min = Math.ceil(min);
		max = Math.floor(max);
		return Math.floor(Math.random() * (max - min + 1)) + min;
	},
	PromisePriority: {
		MICROTASK: -1, // only avaliable if supported by environment
		BACKGROUND_TASK: 0, // default
		VISIBLE_TASK: 1, // default by postTask()
		BLOCKING_TASK: 2,
	},
	run_task: function (func, promisePriority) {
		if (!Number.isInteger(promisePriority)) throw new Error("run_task: Illegal priority: " + promisePriority);
		if (promisePriority < 0 || promisePriority > 2) throw new Error("run_task: Illegal promise priority!");
		try {
			if (window.scheduler && window.scheduler.postTask) {
				var pri = null;
				if (promisePriority === 0) {
					pri = "background";
				} else if (promisePriority === 1) {
					pri = "user-visible";
				} else if (promisePriority === 2) {
					pri = "user-blocking";
				}
				if (pri === null) throw new Error("run_task: Failed to convert task priority!");
				return window.scheduler.postTask(func, { priority: pri }).result;
			} else if (window.Promise) {
				if (typeof PromiseQueuePlus !== "undefined" && window.promise_queue) {
					if (promisePriority >= 1) return window.promise_queue.push(func);
					return window.promise_queue.unshift(func);
				} else {
					return new window.Promise(func);
				}
			} else {
				return (function () {
					var n = func();
					return {
						value: n,
						then: function (y) {
							y(n);
						},
					};
				})();
			}
		} catch (e) {
			console.error(e);
		}
	},
	run_promise: function (func) {
		this.run_task(func, nTube.PromisePriority.BACKGROUND_TASK);
	},
	/**
	 * data format:
	 * {
	 *
	 * }
	 */
	getAccelerationInfo: function (data) {
		if (!this.isSupported() || data === null || data === undefined) {
			return null;
		}
		var enable6ChannelAudio = data.enable6ChannelAudio;
		var enableH264 = data.enableH264;
		var enableH265 = data.enableH265;
		var enableWebM = data.enableWebM;
		var enableAV1 = data.enableAV01;
		var enable50FPS = data.enable50FPS;
		var enableUHQ = data.enable1440AndHigher;
		const VIDEO_CODECS = [];
		const AUDIO_CODECS = ['audio/webm; codecs="opus"', 'audio/mp4; codecs="mp4a.40.2"'];
		if (enableH264) {
			VIDEO_CODECS.pushArray(['video/mp4; codecs="avc1.4d400c"', 'video/mp4; codecs="avc1.4d4015"', 'video/mp4; codecs="avc1.4d401e"', 'video/mp4; codecs="avc1.640028"']);
		}
		if (enableH265) {
			VIDEO_CODECS.pushArray(['video/mp4; codecs="hev1.1.6.L93.90"', 'video/mp4; codecs="hev1.1.6.L93.B0"']);
		}
		if (enableWebM) {
			VIDEO_CODECS.pushArray(['video/webm; codecs="vp9"']);
		}
		if (enableAV1) {
			VIDEO_CODECS.pushArray(['video/mp4; codecs="av01.0.01M.08"', 'video/mp4; codecs="av01.0.04M.08"', 'video/mp4; codecs="av01.0.05M.08"', 'video/mp4; codecs="av01.0.08M.08"']);
		}
		if (enable6ChannelAudio) {
			AUDIO_CODECS.push('audio/mp4; codecs="mp4a.40.5"');
		}
		const FRAMERATES = [24, 60];
		if (enable50FPS) {
			FRAMERATES.push(50);
		}
		const RESOLUTIONS = [
			[1920, 1080],
			[1280, 720],
			[854, 480],
			[640, 360],
			[426, 240],
			[256, 144],
		];
		if (enableUHQ) {
			RESOLUTIONS.pushArray([
				[7680, 4320],
				[3840, 2160],
				[2560, 1440],
			]);
		}
		var results = {
			acceleration_api_version: "0.0.4-D",
			results: [],
		};
		for (var i0 = 0; i0 < AUDIO_CODECS.length; i0++) {
			const audioCodec = AUDIO_CODECS[i0];
			nTubeNext.VideoAcceleration.run_promise(function () {
				for (var i1 = 0; i1 < VIDEO_CODECS.length; i1++) {
					const videoCodec = VIDEO_CODECS[i1];
					for (var i2 = 0; i2 < FRAMERATES.length; i2++) {
						const fps = FRAMERATES[i2];
						for (var i3 = 0; i3 < RESOLUTIONS; i3++) {
							const resolution = RESOLUTIONS[i3];
							const config = {
								type: "media-source",
								audio: {
									contentType: audioCodec,
									channels: audioCodec === 'audio/mp4; codecs="mp4a.40.5"' ? "6" : "2",
									bitrate: nTubeNext.VideoAcceleration.randomInt(80000, 180266),
									samplerate: 48000,
								},
								video: {
									contentType: videoCodec,
									width: resolution[0],
									height: resolution[1],
									framerate: fps.toString(),
									bitrate: nTubeNext.VideoAcceleration.randomInt(60000, 380266),
								},
							};
							navigator.mediaCapabilities.decodingInfo(config).then(function (result) {
								var _result = nTubeNext.VideoAcceleration.AccelerationResult.UNSUPPORTED;
								if (result.supported) {
									if (result.smooth && result.powerEfficient) {
										_result = nTubeNext.VideoAcceleration.AccelerationResult.FULLY_ACCELERATED;
									} else if (result.smooth && !result.powerEfficient) {
										_result = nTubeNext.VideoAcceleration.AccelerationResult.SEMI_ACCELERATED;
									} else {
										_result = nTubeNext.VideoAcceleration.AccelerationResult.UNACCELERATED;
									}
								}
								var result = {
									tested_config: config,
									results: result,
									result: _result,
								};
								results.results.push(result);
							});
						}
					}
				}
			});
		}
		return results;
	},
	getAccelerationFor: function (data, callback) {
		if (!this.isSupported() || data === null || data === undefined) {
			return null;
		}
		try {
			var results = {
				acceleration_api_version: "0.0.4-C",
				result: "FAILED",
			};
			const config = {
				type: "media-source",
				audio: {
					contentType: data.audioCodec,
					channels: data.audioCodec !== undefined && data.audioCodec === 'audio/mp4; codecs="mp4a.40.5"' ? "6" : "2",
					bitrate: nTubeNext.VideoAcceleration.randomInt(80000, 180266),
					samplerate: 48000,
				},
				video: {
					contentType: data.videoCodec,
					width: data.width,
					height: data.height,
					framerate: data.fps,
					bitrate: nTubeNext.VideoAcceleration.randomInt(60000, 380266),
				},
			};
			var c = null;
			var n = navigator.mediaCapabilities
				.decodingInfo(config)
				.then(function (result) {
					var _result = nTubeNext.VideoAcceleration.AccelerationResult.UNSUPPORTED;
					if (result.supported) {
						if (result.smooth && result.powerEfficient) {
							_result = nTubeNext.VideoAcceleration.AccelerationResult.FULLY_ACCELERATED;
						} else if (result.smooth && !result.powerEfficient) {
							_result = nTubeNext.VideoAcceleration.AccelerationResult.SEMI_ACCELERATED;
						} else {
							_result = nTubeNext.VideoAcceleration.AccelerationResult.UNACCELERATED;
						}
					}
					var __results = {
						acceleration_api_version: "0.0.4-D",
						tested_config: config,
						results: result,
						result: _result,
					};
					callback(__results);
				})
				.catch(function (e) {
					console.debug(config);
					console.error(e);
				});
		} catch (e) {
			console.error(e);
			return null;
		}
	},
	getAccelerationForMultiple: function (datas) {
		if (!this.isSupported() || datas === null || datas.length === 0) {
			return null;
		}
		const _RESULTS = [];
		for (var i = 0; i < datas.length; i++) {
			const data = datas[i];
			try {
				var results = {
					acceleration_api_version: "0.0.4-C",
				};
				const config = {
					type: "media-source",
					audio: {
						contentType: data.audioCodec,
						channels: data.audioCodec !== undefined && data.audioCodec === 'audio/mp4; codecs="mp4a.40.5"' ? "6" : "2",
						bitrate: nTubeNext.VideoAcceleration.randomInt(80000, 180266),
						samplerate: 48000,
					},
					video: {
						contentType: data.videoCodec,
						width: data.width,
						height: data.height,
						framerate: data.fps,
						bitrate: nTubeNext.VideoAcceleration.randomInt(60000, 380266),
					},
				};
				navigator.mediaCapabilities.decodingInfo(config).then(function (result) {
					var _result = nTubeNext.VideoAcceleration.AccelerationResult.UNSUPPORTED;
					if (result.supported) {
						if (result.smooth && result.powerEfficient) {
							_result = nTubeNext.VideoAcceleration.AccelerationResult.FULLY_ACCELERATED;
						} else if (result.smooth && !result.powerEfficient) {
							_result = nTubeNext.VideoAcceleration.AccelerationResult.SEMI_ACCELERATED;
						} else {
							_result = nTubeNext.VideoAcceleration.AccelerationResult.UNACCELERATED;
						}
					}
					var result = {
						tested_config: config,
						results: result,
						result: _result,
					};
					_RESULTS.push(result);
				});
			} catch (e) {
				console.error(e);
				return null;
			}
		}
		return _RESULTS;
	},
};
nTubeNext.Platform = {
	isChromeFunc: function () {
		try {
			return (typeof window.chrome === "object" || typeof window.chrome.runtime === "object" || typeof window.chrome.csi === "function") && typeof InstallTrigger !== "object";
		} catch (e) {
			return false;
		}
	},
	getVendor: function () {
		var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(" OPR/") >= 0;
		var isFirefox = typeof InstallTrigger !== "undefined";
		var isSafari =
			/constructor/i.test(window.HTMLElement) ||
			(function (p) {
				return p.toString() === "[object SafariRemoteNotification]";
			})(!window["safari"] || (typeof safari !== "undefined" && safari.pushNotification));
		var isIE = /*@cc_on!@*/ false || !!document.documentMode;
		var isEdge = !isIE && !!window.StyleMedia;
		var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
		var isEdgeChromium = isChrome && navigator.userAgent.indexOf("Edg") != -1;
		var isBlink = (isChrome || isOpera) && !!window.CSS;
		if (isOpera) return "opera";
		else if (isFirefox) return "firefox";
		else if (isSafari) return "safari";
		else if (isIE) return "ie";
		else if (isEdge) return "edge";
		else if (isChrome || isEdgeChromium || (this.isChromeFunc && this.isChromeFunc())) return "chrome";
		else if (isBlink) return "blink";
		else return "N/A";
	},
	getBrowser: function () {
		if (navigator.userAgentData) {
			const browser_brands = navigator.userAgentData.brands;
			if (browser_brands !== null && browser_brands !== undefined && browser_brands.length > 0) {
				var browser_info_obj;
				for (var i = 0; i < browser_brands.length; i++) {
					const brand = browser_brands[i];
					if (brand === null || brand === undefined || !brand["brand"]) continue;
					if (brand["brand"] && (brand["brand"].contains("Not A") || brand["brand"].contains("Brand"))) continue;
					browser_info_obj = brand;
					break;
				}
				if (browser_info_obj !== null && browser_info_obj !== undefined && browser_info_obj["version"]) {
					try {
						var true_brand = browser_info_obj["brand"];
						if (true_brand === "Chromium") {
							true_brand = "Chrome";
						}
						return {
							name: true_brand,
							version: parseInt(browser_info_obj["version"]),
						};
					} catch (ex) {
						console.error("Failed to get hints, falling back...", ex);
					}
				}
			}
		}
		var ua = navigator.userAgent,
			tem,
			M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
		if (/trident/i.test(M[1])) {
			tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
			return { name: "IE", version: tem[1] || "" };
		}
		if (M[1] === "Chrome") {
			tem = ua.match(/\bOPR|Edge\/(\d+)/);
			if (tem != null) {
				return { name: "Opera", version: tem[1] };
			}
		}
		M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, "-?"];
		if ((tem = ua.match(/version\/(\d+)/i)) != null) {
			M.splice(1, 1, tem[1]);
		}
		return {
			name: M[0],
			version: M[1],
		};
	},
	_tryParseInt: function (i) {
		try {
			return parseInt(i);
		} catch (E) {
			return null;
		}
	},
	is: function (payload) {
		/* example: vendor=chrome;version>=85;feature=portals */
		if (payload === null || payload === undefined || payload.length === 0) return false;
		const tasks = payload.split(";");
		for (var i = 0; i < tasks.length; i++) {
			const task = tasks[i];
			const isLast = i == tasks.length - 1;
			if (task.startsWith("vendor")) {
				const vendor = task.split("=")[1];
				if (vendor !== this.getVendor()) return false;
				else if (isLast) return true;
				else continue;
			} else if (task.startsWith("version")) {
				if (task.contains(">=")) {
					const _ver = task.split(">=")[1];
					const ver = this._tryParseInt(_ver);
					if (ver === null) {
						console.warn("Platform::is: Unknown expected version: " + _ver);
						return false;
					}
					const browser = this.getBrowser();
					const browserVersion = this._tryParseInt(browser["version"]);
					if (browserVersion === null) {
						console.warn("Platform::is: Unknown browser version: " + browser["version"]);
						return false;
					}
					if (isLast) return browserVersion >= ver;
					else if (!(browserVersion >= ver)) return false;
					else continue;
				} else if (task.contains("<=")) {
					const _ver1 = task.split("<=")[1];
					const ver1 = this._tryParseInt(_ver1);
					if (ver1 === null) {
						console.warn("Platform::is: Unknown expected version: " + _ver1);
						return false;
					}
					const browser1 = this.getBrowser();
					const browserVersion1 = this._tryParseInt(browser1["version"]);
					if (isLast) return browserVersion1 <= ver1;
					else if (!(browserVersion1 <= ver1)) return false;
					else continue;
				} else if (task.contains("<")) {
					const _ver2 = task.split("<")[1];
					const ver2 = this._tryParseInt(_ver2);
					if (ver2 === null) {
						console.warn("Platform::is: Unknown expected version: " + _ver2);
						return false;
					}
					const browser2 = this.getBrowser();
					const browserVersion2 = this._tryParseInt(browser2["version"]);
					if (isLast) return browserVersion2 < ver2;
					else if (!(browserVersion2 < ver2)) return false;
					else continue;
				} else if (task.contains(">")) {
					const _ver3 = task.split(">")[1];
					const ver3 = this._tryParseInt(_ver3);
					if (ver3 === null) {
						console.warn("Platform::is: Unknown expected version: " + _ver3);
						return false;
					}
					const browser3 = this.getBrowser();
					const browserVersion3 = this._tryParseInt(browser3["version"]);
					if (isLast) return browserVersion3 > ver3;
					else if (!(browserVersion3 > ver3)) return false;
					else continue;
				} else if (task.contains("=")) {
					const _ver4 = task.split("=")[1];
					const ver4 = this._tryParseInt(_ver4);
					if (ver4 === null) {
						console.warn("Platform::is: Unknown expected version: " + _ver4);
						return false;
					}
					const browser4 = this.getBrowser();
					const browserVersion4 = this._tryParseInt(browser4["version"]);
					if (isLast) return browserVersion4 === ver4;
					else if (browserVersion4 !== ver4) return false;
					else continue;
				} else throw new Error("Platform::is: Unknown operation within: " + task);
			} else if (task.startsWith("feature")) {
				const feature = task.split("=")[1];
				switch (feature) {
					case "portals":
						return "HTMLPortalElement" in window;
					case "native_sync":
						return typeof MediaController !== "undefined";
					case "animation_frame_callback":
						return typeof requestAnimationFrame === "function";
					case "web_codecs":
						return "VideoDecoder" in window && "VideoEncoder" in window;
					case "webgpu":
						return "gpu" in navigator;
					case "mse":
						return "MediaSource" in window || "WebKitMediaSource" in window;
					case "broadcast_channels":
						return "BroadcastChannel" in window;
					case "service_workers":
						return "serviceWorker" in navigator;
					case "web_workers":
						return typeof Worker !== "undefined";
					case "webassembly":
					case "wasm":
						return (function () {
							try {
								if (typeof WebAssembly === "object" && typeof WebAssembly.instantiate === "function") {
									const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
									if (module instanceof WebAssembly.Module) return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
								}
							} catch (_ignored) {}
							return false;
						})();
					case "limited_cookie_max_duration":
						return nTubeNext.Platform.is("vendor=chrome;version>=104");
					default:
						throw new Error("Platform::is: Unknown feature: " + feature);
				}
			}
		}
		return false;
	},
};
const addPreviewPortal = function () {
	const args = arguments;
	if (args === null || args === undefined || args.length === 0) {
		throw new Error("Invalid arguments.");
	}
	const url0 = args[0];
	var position = "bl";
	if (args.length >= 2) {
		position = args[1];
	}
	var truePosition;
	var sideAlign;
	switch (position) {
		case "br": {
			truePosition = "bottom right";
			sideAlign = "right: 20px;";
			break;
		}
		case "bl":
		default: {
			truePosition = "bottom left";
			sideAlign = "left: 20px;";
			break;
		}
	}
	const existingPortal = document.querySelector("portal");
	if (existingPortal) {
		existingPortal.remove();
	}
	const style = document.createElement("style");
	style.innerHTML =
		"portal { " +
		"         position:fixed; " +
		"         width: 100%; " +
		"         height: 100%; " +
		"         opacity: 0; " +
		"         box-shadow: 0 0 20px 10px #999; " +
		"         transform: scale(0.4); " +
		"         transform-origin: " +
		truePosition +
		"; " +
		"         bottom: 20px; " +
		"         " +
		sideAlign +
		" " +
		"         animation-name: fade-in; " +
		"         animation-duration: 1s; " +
		"         animation-delay: 2s; " +
		"         animation-fill-mode:forwards; " +
		"}" +
		".portal-transition { " +
		"         transition: transform 0.8s; " +
		"}" +
		"@media (prefers-reduced-motion: reduce) { " +
		"         .portal-transition { " +
		"             transition: transform 0.001s; " +
		"         }" +
		"}" +
		".portal-reveal { " +
		"         transform: scale(1.0) translateX(-20px) translateY(20px); " +
		"}" +
		"@keyframes fade-in { " +
		"         0%   { opacity: 0; } " +
		"         100% { opacity: 1; } " +
		"}";
	const portal = document.createElement("portal");
	portal.src = url0;
	portal.classList.add("portal-transition");
	portal.addEventListener("click", function (evt) {
		portal.classList.add("portal-reveal");
	});
	portal.addEventListener("transitionend", function (evt) {
		if (evt.propertyName == "transform") {
			portal.activate({ data: { isActive: "yes" } });
		}
	});
	document.body.append(style, portal);
};
window.addPreviewPortal = addPreviewPortal;

if (nTubeNext.Platform.is("feature=service_workers")) {
	window.addEventListener("load", function () {
		navigator.serviceWorker.register("/ntube_service_worker.js").then(
			function (registration) {
				console.log("[nTubeNext] Installed service worker with scope: ", registration.scope);
			},
			function (err) {
				console.log("[nTubeNext] Failed to install service worker.");
				console.error(err);
			}
		);
	});
}
